package com.njcb.ams.service.workflow;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.engine.HistoryService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.task.Task;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;

/**
 * 流程图服务
 * 
 * @author liuyanlong
 *
 */
@Service
public class ProcessDiagramService {

	@Autowired
	private RepositoryService repositoryService;
	@Autowired
	private ManagementService managementService;
	@Autowired
	private TaskService taskService;
	@Autowired
	private SpringProcessEngineConfiguration processEngineConfiguration;
	@Autowired
	private HistoryService historyService;
	@Autowired
	private ProcessInstanceDiagramCmd processInstanceDiagramCmd;

	/**
	 * 带跟踪的流程图片
	 * 
	 * @throws IOException
	 */
	public Map<String, List<String>> processDiagramHighLightAll(String processInstanceId) throws IOException {

		// 获取历史流程实例
		HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery()
				.processInstanceId(processInstanceId).singleResult();
		Context.setProcessEngineConfiguration(processEngineConfiguration);

		ProcessDefinitionEntity definitionEntity = (ProcessDefinitionEntity) repositoryService
				.getProcessDefinition(hpi.getProcessDefinitionId());

		List<HistoricActivityInstance> highLightedActivitList = historyService.createHistoricActivityInstanceQuery()
				.processInstanceId(processInstanceId).list();
		// 高亮环节ID集合
		List<String> highLightedActivitis = new ArrayList<String>();
		// 高亮线路id集合
		List<String> highLightedFlows = getHighLightedFlows(definitionEntity, highLightedActivitList);

		for (HistoricActivityInstance tempAcvtivity : highLightedActivitList) {
			String activityId = tempAcvtivity.getActivityId();
			highLightedActivitis.add(activityId);
		}

		Map<String, List<String>> map = new HashMap<String, List<String>>();
		map.put("highLightedActivitis", highLightedActivitis);
		map.put("highLightedFlows", highLightedFlows);
		return map;

	}

	/**
	 * 获取需要高亮的线
	 */
	private List<String> getHighLightedFlows(ProcessDefinitionEntity processDefinitionEntity,
			List<HistoricActivityInstance> historicActivityInstances) {
		List<String> highFlows = new ArrayList<String>();// 用来保存高亮线的flowid
		for (int i = 0; i < historicActivityInstances.size() - 1; i++) {
			ActivityImpl activityImpl = processDefinitionEntity.findActivity(// 获取节点定义详细信息
					historicActivityInstances.get(i).getActivityId());
			List<ActivityImpl> sameStartTimeNodes = new ArrayList<ActivityImpl>();

			ActivityImpl sameActivityImpl1 = processDefinitionEntity
					.findActivity(historicActivityInstances.get(i + 1).getActivityId());// 保存需要开始时间的相同节点
			// 将后面第一个借点放在时间相投的节点集合
			sameStartTimeNodes.add(sameActivityImpl1);
			for (int j = i + 1; j < historicActivityInstances.size() - 1; j++) {
				HistoricActivityInstance activityImpl1 = historicActivityInstances.get(j);// 后续第一个节点
				HistoricActivityInstance activityImpl2 = historicActivityInstances.get(j + 1);// 后续第二个节点
				if (activityImpl1.getStartTime().equals(activityImpl2.getStartTime())) {
					// 如果第一个节点和第二个节点开始时间相同保存
					ActivityImpl sameActivityImpl2 = processDefinitionEntity
							.findActivity(activityImpl2.getActivityId());
					sameStartTimeNodes.add(sameActivityImpl2);
				} else {
					// 不相同跳出循环
					break;
				}
			}
			List<PvmTransition> pvmTransitions = activityImpl.getOutgoingTransitions();// 节点出去的线
			for (PvmTransition pvmTransition : pvmTransitions) {
				// 遍历所有线
				ActivityImpl pvmActivityImpl = (ActivityImpl) pvmTransition.getDestination();
				//
				if (sameStartTimeNodes.contains(pvmActivityImpl)) {
					highFlows.add(pvmTransition.getId());
				}
			}
		}
		return highFlows;

	}

	/**
	 * 获取高亮流程图 方法功能描述：
	 * 
	 * @param taskId
	 * @return
	 * @throws Exception
	 */
	public String processDiagramHighLightSingle(String taskId) throws Exception {
		String processDiagram = null;
		ByteArrayOutputStream out = null;
		String processDefinitionId = null;
		String processInstanceId = null;
		if (null != taskId) {
			Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
			if(null == task){
				HistoricTaskInstance historyTask = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
				processInstanceId = historyTask.getProcessInstanceId();
			}else{
				processInstanceId = task.getProcessInstanceId();
			}

			List<HistoricProcessInstance> instanceList = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).list();
			if(instanceList.size() > 0){
				HistoricProcessInstance processInstance = instanceList.get(0);
				processDefinitionId = processInstance.getProcessDefinitionId();
			}
			
			Map<String, List<String>> activitys = this.processDiagramHighLightAll(processInstanceId);
			List<String> highLightedActivitis = activitys.get("highLightedActivitis");
			List<String> highLightedFlows = activitys.get("highLightedFlows");
			processInstanceDiagramCmd.setProcessInstanceInfo(processDefinitionId, processInstanceId, highLightedActivitis, highLightedFlows);
			InputStream is = managementService.executeCommand(processInstanceDiagramCmd);
			out = new ByteArrayOutputStream(1024);
			byte[] temp = new byte[1024];
			int size = 0;
			while ((size = is.read(temp)) != -1) {
				out.write(temp, 0, size);
			}
			is.close();
			byte[] content = out.toByteArray();
			processDiagram = new String((JSON.toJSONString(content)).getBytes("iso8859-1"), "UTF-8");
		}
		return processDiagram;
	}

}
